package com.cheyun.netsalev3.utils.api.dm

import android.net.ParseException
import android.os.Looper
import android.util.Log
import android.widget.Toast
import com.cheyun.netsalev3.MyApplication
import com.cheyun.netsalev3.utils.AppCongfig
import com.cheyun.netsalev3.utils.api.DmBaseResp
import com.google.gson.JsonParseException
import io.reactivex.Observer
import io.reactivex.disposables.Disposable
import org.json.JSONException
import retrofit2.HttpException
import java.io.IOException

/**
 * @author Michael
 * @date  2018/11/6 - 16:12.
 */
abstract class DmApiCallback<M> : Observer<M> {

    /**
     * Unauthorized/未授权
     */
    private val UNAUTHORIZED = 401

    /**
     * 请求出错
     */
    private val BAD_REQUEST = 400

    /**
     * Forbidden/禁止
     */
    private val FORBIDDEN = 403

    /**
     * Not Found/未找到
     */
    private val NOT_FOUND = 404

    /**
     * Method Not Allowed/方法未允许
     */
    private val METHOD_NOT_ALLOWED = 405

    /**
     * Request Timeout/请求超时
     */
    private val REQUEST_TIMEOUT = 408

    /**
     * Internal Server Error/内部服务器错误
     */
    private val INTERNAL_SERVER_ERROR = 500

    /**
     * Bad Gateway/错误的网关
     */
    private val BAD_GATEWAY = 502

    /**
     * Service Unavailable/服务无法获得
     */
    private val SERVICE_UNAVAILABLE = 503

    /**
     * Gateway Timeout/网关超时
     */
    private val GATEWAY_TIMEOUT = 504

    /**
     * 统一处理网络、数据格式转换、io读写错误，将业务定义的错误留给子类实现
     *
     * @param e
     */
    override fun onError(e: Throwable) {
        var e = e

        Log.e("DmApiCallback", e?.message)

        val throwable = e
        //获取最根源的异常
        if (throwable != null && throwable.cause != null) {
            e = throwable
        }

        val ex: DmApiException

        //HTTP错误
        if (e is HttpException) {
            val httpException = e as HttpException?
            when (httpException!!.code()) {

                //未授权
                UNAUTHORIZED -> {
                    ex = DmApiException(UNAUTHORIZED, AppCongfig.UNAUTHORIZED)
                    onError2(ex)
                }

                //请求方法不允许
                METHOD_NOT_ALLOWED -> {
                    ex = DmApiException(METHOD_NOT_ALLOWED, AppCongfig.METHOD_NOT_ALLOWED)
                    onError2(ex)
                }

                //禁止访问
                FORBIDDEN -> {
                    ex = DmApiException(FORBIDDEN, AppCongfig.FORBIDDEN)
                    onError2(ex)
                }

                //无法找到资源
                NOT_FOUND -> {
                    ex = DmApiException(NOT_FOUND, AppCongfig.NOT_FOUND)
                    onError2(ex)
                }

                //请求超时
                REQUEST_TIMEOUT -> {
                    ex = DmApiException(REQUEST_TIMEOUT, AppCongfig.REQUEST_TIMEOUT)
                    onError2(ex)
                }

                //服务器内部错误
                INTERNAL_SERVER_ERROR -> {
                    ex = DmApiException(INTERNAL_SERVER_ERROR, AppCongfig.INTERNAL_SERVER_ERROR)
                    onError2(ex)
                }
                //请求出错
                BAD_REQUEST -> {
                    ex = DmApiException(BAD_REQUEST, AppCongfig.BAD_REQUEST)
                    onError2(ex)
                }
                //网络请求错误
                GATEWAY_TIMEOUT, BAD_GATEWAY, SERVICE_UNAVAILABLE -> {
                    ex = DmApiException(1, AppCongfig.BAD_NET_WORK)
                    onError2(ex)
                }
                else -> {
                }
            }
        } else if (e is JsonParseException
                || e is JSONException
                || e is ParseException) {

            Log.e("DmApiCallback", e.message)
            ex = DmApiException(0, AppCongfig.PARSE_ERROR)
            onError2(ex)
        } else if (e is IOException) {
            ex = DmApiException(0, AppCongfig.BAD_NET_WORK)
            onError2(ex)
        } else {
            Log.e("DmApiCallback", e!!.message)
            Log.e("", "最终的错误 ： " + e.message)
            ex = DmApiException(0, AppCongfig.UNKNOW_ERROR)
            onError2(ex)
        }//数据解析出错
    }


    override fun onNext(t: M) {
        if (t != null && t is DmBaseResp<*,*>) {
            val resp = t as DmBaseResp<*,*>
            var code = resp.code
            if(code == 0){
                onSuccess(t)
            }else {
                var msg = resp.msg
                if(!msg.isNullOrEmpty()){
                    val ex = DmApiException(0, msg.toString())
                    onError(ex)
                }
            }
        }
    }

    override fun onComplete() {

    }

    override fun onSubscribe(d: Disposable) {

    }

    /**
     * 成功返回数据回调
     *
     * @param t
     */
    protected abstract fun onSuccess(t: M)

    private fun onError2(ex: DmApiException) {
        onError(ex)
        Looper.prepare()
        Toast.makeText(MyApplication.getInstance(), ex.getMessage(), Toast.LENGTH_LONG).show()
        Looper.loop()

    }

    /**
     * 错误回调 统一处理
     *
     * @param ex
     */
    protected abstract fun onError(ex: DmApiException)


}